<template>
  <div ref="RefCard" :class="['form-card', { mini }]">
    <h4 v-if="title" style="margin-bottom: 12px;">{{ title }}</h4>
    <slot name="top"></slot>
    <ElForm :inline="true" :model="data" :label-width="instance.label_width" :rules="instance.rule">
      <template v-for="(label, prop) in labels" :key="prop">
        <template v-if="label">
          <ElFormItem v-if="!label.show || label.show({ data, type: 'form', isPhone: false })" :prop="label.prop"
            :label="showLabel && label.label ? label.label + ':' : ''" :label-width="label.label_width"
            :style="{ width: computedWidth(label.formWidth), marginBottom: instance.spance + 'px', }">
            <component v-if="label.type === 'customize'"
              :is="label.vform({ prop: label.prop as keyof T & string, data, value: data[label.prop as keyof T & string] })">
            </component>
            <component v-else :is="formRender.render(toValue(data), label)"></component>
          </ElFormItem>
        </template>
      </template>
      <ElFormItem v-if="Object.keys(instance.labels).length === 1">
        <ElInput placeholder="单个输入框补位，防止自动提交" :display="true" style="opacity: 0; height: 0"></ElInput>
      </ElFormItem>
    </ElForm>
  </div>
  <slot></slot>
</template>

<script lang="ts" setup generic="T extends Record<string, any>">
import { ElInput, ElForm, ElFormItem } from "element-plus";
import { Form } from "@b/model/base/form";
import { ref, onMounted, computed, toValue } from "vue";
import { FormRender, computedWidth } from "./render_item"
import type { interForm } from "@b/model/base/type";

interface prop {
  instance: Form<T>;
  label_prop?: string
  mini?: boolean;
  title?: string;
  cover?: string;
}
const showLabel = ref(true);
const RefCard = ref();
const { instance, cover = "33%", label_prop = "labels" } = defineProps<prop>();
const data = computed(() => instance.data);
//@ts-ignore
const l = toValue(instance[label_prop]) as { [key in keyof T & string]?: interForm<T, key> }
if (!l) throw new Error('bForm 组件需要 labels 属性')
const labels = computed(() => Object.values(l).sort((a, b) => (a.sortBy || Infinity) - (b.sortBy || Infinity)))
const formRender = new FormRender<T, keyof T & string>();

onMounted(() => {
  const value = RefCard.value.offsetWidth;
  if (value && value < 370) {
    showLabel.value = false;
  }
});
</script>

<style scoped>
.form-card {
  position: relative;
  border-radius: 0 0 12px 12px;
  background: var(--el-bg-color);
  padding: 20px;
}

.form-card.mini {
  padding: 0;
}

.mini .el-form-item {
  width: v-bind(cover);
  margin-right: 0;
}

.form-card+.form-card {
  border-radius: 12px;
}

.el-form-item {
  width: calc(v-bind(cover) - 32px);
  min-width: 140px;
  align-items: center;
}
</style>